﻿#region License
//  Distrubted Under the GNU Public License version 2 (GPLv2)
// ========================================
// 
//  QuizzMasterStudio Version 3 
//  Copyright © 2012 , The Sparks (Autism App Jam 2014)
//  All rights reserved.  
// 
// Robert Long, Zephyr Yao, Hillary Chansavang, Li Xiao, Arial Xiao
// 
//  This program is free software: you can redistribute it and/or modify
//  it under the terms of the GNU General Public License as published by
//  the Free Software Foundation, either version 3 of the License, or
//  (at your option) any later version.
//  
//  This program is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU General Public License for more details.
//  
//  You should have received a copy of the GNU General Public License
//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
//  The full license is also included in the root folder.
// 
// Robert Long
//  Email: rbtLong@live.com
#endregion

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Text.RegularExpressions;
using System.Windows.Input;
using Core.Annotations;
using Core.Features.FeatureBase;
using Core.ScoreSystem;
using Core.User;
using Core.Util;
using Microsoft.Phone.Controls;

namespace Core.Features.FillIn.ViewModel
{

    public class PhoneNumberGameVM : INotifyPropertyChanged, IFeature
    {
        private const string _fillInTitle = "Fill in the Blanks";
        private int _selectedTab;
        private Pivot _mainPivot;
        private readonly List<DigitScrambler> _scramblers = new List<DigitScrambler>();
        private int _correctDigits;

        public string FillInTitle
        {
            get { return _fillInTitle; }
        }
        public string PhoneNumber { get; set; }
        private static bool isValidPhoneNumber(object o)
            {
                if (o is string)
                {
                    var str = o as string;
                    var nValid = new Regex("[0-9]*");
                    if (nValid.IsMatch(str) && str.Length == 10)
                        return true;
                }
                return false;
            }

        public string IncorrectResultSentence 
        {
            get
            {
                return string.Format(
                    "You got {0} correct digits.\nBetter Luck next time.", 
                    _correctDigits);
            }
        }
        public string IncorrectResultDisplayPhoneNumber
        {
            get
            {
                if (PhoneNumber.Length < 7)
                    return string.Empty;
                var prefix = PhoneNumber.Substring(3, 3);
                var suffix = PhoneNumber.Substring(6, 4);
                return string.Format(
                    "Your Phone #: {0}-{1}",
                    prefix, suffix);
            }
        }

        public event EventHandler Correct = delegate { };
        public event EventHandler Incorrect = delegate { }; 

        public ICommand CmdSubmitPhoneNumber
        {
            get
            {
                return new CommandHandler(o =>
                {
                    if (o is string)
                    {
                        UserProfileSession.GetSession().User.PhoneNumber = o as string;
                        UserProfileSession.SaveSession();
                        PhoneNumber = o as string;
                        initGame(PhoneNumber);
                        changePivotIndex(1);
                    }
                }, isValidPhoneNumber);
            }
        }
        public ICommand CmdXClose
        {
            get
            {
                return new CommandHandler(o => 
                    Finished(this, new EventArgs()));
            }
        }
        public ICommand CmdSubmitGame
        {
            get
            {
                return new CommandHandler(o =>
                {
                    if (isCorrectPhoneNumber())
                    {
                        changePivotIndex(2);
                        Correct(this, new EventArgs());
                    }
                    else
                    {
                        changePivotIndex(3);
                        Incorrect(this, new EventArgs());
                    }
                    OnPropertyChanged("IncorrectSentence");
                    scoreGame();
                });
            }
        }
        public ICommand CmdResultOk
        {
            get
            {
                return new CommandHandler(o =>
                    Finished(this, new EventArgs()));
            }
        }

        #region Digits

        private int _digit1Idx = -1;
        private int _digit2Idx = -1;
        private int _digit3Idx = -1;
        private int _digit4Idx = -1;
        private int _digit5Idx = -1;
        private int _digit6Idx = -1;
        private int _digit7Idx = -1;
        private int _digit8Idx = -1;
        private int _digit9Idx = -1;
        private int _digit10Idx = -1;

        public int[] Digit1
        {
            get
            {
                if (scramberInitialized())
                    return _scramblers[0].Possibilities;
                return new[]{0};
            }
        }
        public int[] Digit2
        {
            get
            {
                if (scramberInitialized())
                    return _scramblers[1].Possibilities;
                return new[] { 0 };
            }
        }
        public int[] Digit3
        {
            get
            {
                if (scramberInitialized())
                    return _scramblers[2].Possibilities;
                return new[] { 0 };
            }
        }
        public int[] Digit4
        {
            get
            {
                if (scramberInitialized())
                    return _scramblers[3].Possibilities;
                return new[] { 0 };
            }
        }
        public int[] Digit5
        {
            get
            {
                if (scramberInitialized())
                    return _scramblers[4].Possibilities;
                return new[] { 0 };
            }
        }
        public int[] Digit6
        {
            get
            {
                if (scramberInitialized())
                    return _scramblers[5].Possibilities;
                return new[] { 0 };
            }
        }
        public int[] Digit7
        {
            get
            {
                if (scramberInitialized())
                    return _scramblers[6].Possibilities;
                return new[] { 0 };
            }
        }
        public int[] Digit8
        {
            get
            {
                if (scramberInitialized())
                    return _scramblers[7].Possibilities;
                return new[] { 0 };
            }
        }
        public int[] Digit9
        {
            get
            {
                if (scramberInitialized())
                    return _scramblers[8].Possibilities;
                return new[] { 0 };
            }
        }
        public int[] Digit10
        {
            get
            {
                if (scramberInitialized())
                    return _scramblers[9].Possibilities;
                return new[] { 0 };
            }
        }

        public int Digit1Idx
        {
            get { return _digit1Idx; }
            set { _digit1Idx = value; }
        }

        public int Digit2Idx
        {
            get { return _digit2Idx; }
            set { _digit2Idx = value; }
        }

        public int Digit3Idx
        {
            get { return _digit3Idx; }
            set { _digit3Idx = value; }
        }

        public int Digit4Idx
        {
            get { return _digit4Idx; }
            set { _digit4Idx = value; }
        }

        public int Digit5Idx
        {
            get { return _digit5Idx; }
            set { _digit5Idx = value; }
        }

        public int Digit6Idx
        {
            get { return _digit6Idx; }
            set { _digit6Idx = value; }
        }

        public int Digit7Idx
        {
            get { return _digit7Idx; }
            set { _digit7Idx = value; }
        }

        public int Digit8Idx
        {
            get { return _digit8Idx; }
            set { _digit8Idx = value; }
        }

        public int Digit9Idx
        {
            get { return _digit9Idx; }
            set { _digit9Idx = value; }
        }

        public int Digit10Idx
        {
            get { return _digit10Idx; }
            set { _digit10Idx = value; }
        }

        #endregion

        private bool scramberInitialized()
        {
            return isValidPhoneNumber(PhoneNumber)
                   && _scramblers.Count == 10;
        }

        public PhoneNumberGameVM(Pivot mainPivot)
        {
            initMainPivot(mainPivot);
            checkUserPhoneNumber_MovePageIfValid();
        }

            private void initMainPivot(Pivot mainPivot)
            {
                _mainPivot = mainPivot;
                _mainPivot.SelectionChanged += (sender, args) =>
                {
                    _mainPivot.SelectedIndex = _selectedTab;
                };
            }

            private void checkUserPhoneNumber_MovePageIfValid()
            {
                PhoneNumber = UserProfileSession.GetSession().User.PhoneNumber;
                if (isValidPhoneNumber(PhoneNumber))
                    changePivotIndex(1);
            }


                private void changePivotIndex(int idx)
                {
                    _selectedTab = idx;
                    _mainPivot.Dispatcher.BeginInvoke(() =>
                        _mainPivot.SelectedIndex = idx);

                    if(_selectedTab == 1 && isValidPhoneNumber(PhoneNumber))
                        initGame(PhoneNumber);
                }

        private void initGame(string pNumber)
        {
            _scramblers.Clear();
            foreach (char digit in pNumber)
                _scramblers.Add(new DigitScrambler(int.Parse(digit.ToString())));
            for(int i=0; i<pNumber.Length; ++i)
                OnPropertyChanged(string.Format("Digit{0}", i + 1));
        }


        private bool isCorrectPhoneNumber()
        {
            selectPositionZero_IfNegativeOneIdx();

            _correctDigits = 0;
            if (Digit4Idx == _scramblers[3].CorrectIdx)
                _correctDigits++;
            if (Digit5Idx == _scramblers[4].CorrectIdx)
                _correctDigits++;
            if (Digit6Idx == _scramblers[5].CorrectIdx)
                _correctDigits++;
            if (Digit7Idx == _scramblers[6].CorrectIdx)
                _correctDigits++;
            if (Digit8Idx == _scramblers[7].CorrectIdx)
                _correctDigits++;
            if (Digit9Idx == _scramblers[8].CorrectIdx)
                _correctDigits++;
            if (Digit10Idx == _scramblers[9].CorrectIdx)
                _correctDigits++;

            OnPropertyChanged("IncorrectResultSentence");
            OnPropertyChanged("IncorrectResultDisplayPhoneNumber");

            return (_correctDigits == 7);
        }

            private void selectPositionZero_IfNegativeOneIdx()
            {
                zeroOut_IfNegative(ref _digit1Idx);
                zeroOut_IfNegative(ref _digit2Idx);
                zeroOut_IfNegative(ref _digit3Idx);
                zeroOut_IfNegative(ref _digit4Idx);
                zeroOut_IfNegative(ref _digit5Idx);
                zeroOut_IfNegative(ref _digit6Idx);
                zeroOut_IfNegative(ref _digit7Idx);
                zeroOut_IfNegative(ref _digit8Idx);
                zeroOut_IfNegative(ref _digit9Idx);
                zeroOut_IfNegative(ref _digit10Idx);
            }

                private void zeroOut_IfNegative(ref int n)
                {
                    if (n == -1)
                        n = 0;
                }

        private void scoreGame()
        {
            int score = 10;
            if (_correctDigits == 7)
                score += 120;
            score += (_correctDigits * 25);

            var usr = UserProfileSession.GetSession().User;
            usr.AppendScore(new ScoreEntry("Phone Game", score));
            UserProfileSession.SaveSession();
        }


        public event PropertyChangedEventHandler PropertyChanged = delegate { };
        [NotifyPropertyChangedInvocator]
        protected virtual void OnPropertyChanged(string propertyName)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            handler(this, new PropertyChangedEventArgs(propertyName));
        }

        public event EventHandler Finished = delegate { };
    }
}
